package GameElements;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JLabel;


import Utils.ImageUtils;

public class Tile 
{
	public static final int nothing=0, castle=1, street=2, farm=3, cloister=4;
	public static final int no_bouclier=0, yes_bouclier=1;
	public static final int n0=0, n1=1, n2=2, e0=3, e1=4, e2=5, s0=6, s1=7, s2=8, w0=9, w1=10, w2=11, c=12;
	
	protected ImageIcon imgTile;
	protected String imgName;
	protected int north;
	protected int east;
	protected int south;
	protected int west;
	protected int center;
	protected int bouclier;
	protected int[] links;
	protected Pawn[] pawn;

	public Tile(String imgName, int[] NESWCB, int[] links)
	{
		init(imgName, NESWCB[0], NESWCB[1], NESWCB[2], NESWCB[3], NESWCB[4], NESWCB[5], links);		
	}
	//constructeur par copie
	public Tile(Tile tileToClone)
	{
		init(tileToClone.imgName, tileToClone.north, tileToClone.east, tileToClone.south, tileToClone.west, tileToClone.center, tileToClone.bouclier, tileToClone.links);
	}
	
	protected void init(String imgName, int north, int east, int south, int west, int center, int bouclier, int[] links)
	{
		this.north = north;
		this.east = east;
		this.south = south;
		this.west = west;
		this.center = center;
		this.bouclier = bouclier;
		
		this.links = links;
		pawn = new Pawn[13];
		
		this.imgName = imgName;
		imgTile = new ImageIcon(imgName);
	}
	
	public void rotate90()
	{ 
		//rotation des coins cardinaux
		int newNorth = west;
		int newEast = north;
		int newSouth = east;
		int newWest = south;
		
		north = newNorth;
		east = newEast;
		south = newSouth;
		west = newWest;
		
		//rotation des liens
		int[] newLinks = new int[12];
		for(int i=0; i<links.length; i++)
			newLinks[(i+3)%links.length]= links[i];
		links = newLinks;
		
		//rotation des positions des pions
		Pawn[] newPawn = new Pawn[13];
		for(int i=0; i<pawn.length-1; i++)
			newPawn[(i+3)%(pawn.length - 1)]= pawn[i];
		newPawn[12]= pawn[12];
		pawn = newPawn;		
		
		//rotation d'imgTile
		imgTile = new ImageIcon(ImageUtils.rotateImage(imgTile.getImage(), 90));
		repaintImg();
	}
	
	public void printInfos()
	{
		String[] tmp = {"", "c", "s", "f"};
		System.out.println(" " + tmp[north]);
		System.out.print("" + tmp[west]);
		System.out.println("  " + tmp[east]);
		System.out.println(" " + tmp[south]);
	}

	protected void repaintImg()
	{
		Image bufferedImg = new BufferedImage(imgTile.getIconWidth(), imgTile.getIconHeight(), BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = (Graphics2D)bufferedImg.getGraphics();
		g2d.drawImage(imgTile.getImage(), 0, 0, null);
		for(int i=0; i< pawn.length; i++)
			if(pawn[i] != null)
			{
				Point p = getPosition(pawn[i], i);
				g2d.drawImage(pawn[i].getImg().getImage(), p.x, p.y, null);		
			}
		imgTile = new ImageIcon(bufferedImg);
	}
	
	protected Point getPosition(Pawn pawn, int indexInTile)
	{
		int hT = imgTile.getIconHeight();
		int wT = imgTile.getIconWidth();
		int hP = pawn.getImg().getIconHeight();
		int wP = pawn.getImg().getIconWidth(); 
		Point p = new Point(0, 0);
		
		switch(indexInTile)
		{
			case n0:
				p.x=wT/2-wP/2-wP; p.y=0;
				break;
			case n1:
				p.x=wT/2-wP/2; p.y=0;
				break;
			case n2:
				p.x=wT/2-wP/2+wP; p.y=0;
				break;
			case e0:
				p.x=wT-wP; p.y=hT/2-hP/2-hP;
				break;
			case e1:
				p.x=wT-wP; p.y=hT/2-hP/2;
				break;
			case e2:
				p.x=wT-wP; p.y=hT/2-hP/2+hP;
				break;
			case s0:
				p.x=wT/2-wP/2+wP; p.y=hT-hP;
				break;
			case s1:
				p.x=wT/2-wP/2; p.y=hT-hP;
				break;
			case s2:
				p.x=wT/2-wP/2-wP; p.y=hT-hP;
				break;
			case w0:
				p.x=0; p.y=hT/2-hP/2+hP;
				break;
			case w1:
				p.x=0; p.y=hT/2-hP/2;
				break;
			case w2:
				p.x=0; p.y=hT/2-hP/2-hP;
				break;
			case c:
				p.x=wT/2-wP/2; p.y=hT/2-hP/2;
				break;
		}
		
		return p;
	}
	
	
	
	//getters
	public ImageIcon getImage(){		
		return imgTile;
	}	
	public int getNorth() {
		return north;
	}
	public int getEast() {
		return east;
	}
	public int getSouth() {
		return south;
	}
	public int getWest() {
		return west;
	}
	public int getCenter() {
		return center;
	}
	public int[] getLinks() {
		return links;
	}
	public Pawn[] getPawn()
	{
		return pawn;
	}
	public Pawn getPawn(int i)
	{
		return pawn[i];
	}
	public Pawn getPionPose() {
		for(int i=0; i<pawn.length; i++)
			if(pawn[i] != null)
				return pawn[i];
		return null;
	}
	public void removePawn(Pawn p)
	{
		for(int i=0; i<pawn.length; i++)
			if(pawn[i] == p)
				pawn[i]=null;
	}
	
	//attention : resultat correct uniquement si index est calculé par findAdaptedIndex 
	protected int getTypePart(int index) {
		int adaptedIndex = findAdaptedIndex(index);
		if(adaptedIndex == n1)
			return north;
		else if(adaptedIndex == e1)
			return east;
		else if(adaptedIndex == s1)
			return south;
		else if(adaptedIndex == w1)
			return west;
		else if(adaptedIndex == c && center == cloister)
			return cloister;
		return farm;//**		
	}
	
	
	//setters
	public void setPawnToAdaptedIndex(Pawn p, int index) {
		int adaptedIndex = findAdaptedIndex(index);
		pawn[adaptedIndex] = p;
		setRole(p, adaptedIndex);
		repaintImg();
	}
	protected void setRole(Pawn p, int index){
		int typePart = getTypePart(index);
		
		if(typePart == farm)
			p.setRole(Pawn.PAYSAN);
		else if(typePart == castle)
			p.setRole(Pawn.CHEVALIER);
		else if(typePart == street)
			p.setRole(Pawn.VOLEUR);
		else if(typePart == cloister)
			p.setRole(Pawn.MOINE);
	}
	
	
	public boolean haveBouclier(){
		if(bouclier == yes_bouclier)
			return true;
		return false;
	}
	public boolean havePawn(Vector<Integer> l){
		for(int i=0; i<l.size(); i++)
			if(pawn[l.get(i)] != null) //si il y'a un pion
				return true;
		return false;
	}
	public boolean havePawn(){
		for(int i=0; i<pawn.length; i++)
			if(pawn[i] != null) //si il y'a un pion
				return true;
		return false;
	}

	
	
	
	//algos
	public int findAdaptedIndex(int index) {//ok
		//si c'est le centre --> ok
		if(index == c)
			return index;
		//si c'est l'un des 4 coins cardinaux --> ok
		if(index==n1 || index==e1 || index==s1 || index==w1)
			return index;
		//sinon trouver une direction cardinal auquelle il est relié
		int linkedCD = find1LinkedCD(index);
		if(linkedCD != -1)
			return linkedCD;
		return index;//sinon garder le meme point		
	}
	
	public int find1LinkedCD(int index)//ok
	{
		for(int i=1; i<12; i=i+3)
			if(links[index] == links[i])
				return i;
		return -1;
	}
	public Vector<Integer> findLinkedCD(int index)//ok
	{
		Vector<Integer> res = new Vector<Integer>();
		for(int i=1; i<12; i=i+3)
			if(links[index] == links[i])
				res.add(i);
		return res;
	}
	public boolean isCLinkedTo1PointMinInCDL(int c, Vector<Integer> cdl)
	{
		for(int i=0; i<cdl.size(); i++)
			if(links[cdl.get(i)] == links[c])
				return true;
		return false;
	}
	
	//juste pour tester
	public void drawPoint(int i)
	{
		pawn[i] = new BasicPawn("img/pawns/yellow_basic.png", Color.red);
		repaintImg();
	}

}
